#!/bin/sh
#
# iptables configuration for redsocks
#

set -e

IPTABLES_WAIT_SECS="10"
IPTABLES="iptables -w $IPTABLES_WAIT_SECS"

. /usr/sbin/balena-config-vars
. /usr/libexec/os-helpers-logging

# $1 - iptables chain
# $2 - iptables target
removeRulesFromChain() {
    _chain=${1}
    _target=${2}
    while true; do
        _idx=$($IPTABLES -t nat -L ${_chain} --line-numbers | \
               grep -m 1 "${_target}" | \
               awk '{print $1}' | \
               head -n 1)


        if [ -z "${_idx}" ]; then
            info "No more ${_target} targets found."
            break
        else
            info "Found ${_target} target at line number: ${_idx}. Deleting..."
            $IPTABLES -t nat -D "${_chain}" "${_idx}" \
                && info "Rule no. ${_idx} deleted." \
                || error "Failed to delete target ${_target} rule no. ${_idx}."
        fi
    done
}


if [ ! -f "$CONFIG_PATH" ]; then
	fail "$CONFIG_PATH does not exist."
else
	info "Found config.json in $CONFIG_PATH ."
fi

if [ ! -d "$BALENA_BOOT_MOUNTPOINT" ]; then
	fail " $BALENA_BOOT_MOUNTPOINT does not exist."
fi

REDSOCKSCONF=${BALENA_BOOT_MOUNTPOINT}/system-proxy/redsocks.conf
NOPROXYFILE=${BALENA_BOOT_MOUNTPOINT}/system-proxy/no_proxy

# README!
# The entire following configuration depends on the redsocks configuration.
# Currently the values used here are forced with a patch on redsocks. If these
# change, you need to refresh the redsocks patch as well.

# Always clear the REDSOCKS chain if it exists (in case we're restarting with a changed configuration)
$IPTABLES -t nat -D OUTPUT -p udp -m owner ! --uid-owner redsocks -j DNAT --dport 53 --to-destination 10.114.103.1:5313 || true
$IPTABLES -t nat -D PREROUTING -p udp -j DNAT --dport 53 --to-destination 10.114.103.1:5313 || true
removeRulesFromChain OUTPUT REDSOCKS
removeRulesFromChain PREROUTING REDSOCKS
$IPTABLES -t nat -F REDSOCKS || true
$IPTABLES -t nat -X REDSOCKS || true

if [ ! -f "$REDSOCKSCONF" ]; then
	info "No proxy configuration found, skipping."
	exit 0
fi

# Setup a bridge interface for redsocks
DNS_INTERFACE_NAME="resin-redsocks"
DNS_INTERFACE_IP="10.114.103.1"
if [ ! -d "/sys/class/net/${DNS_INTERFACE_NAME}" ]; then
	ip link add name ${DNS_INTERFACE_NAME} type bridge
fi
if [ "$(cat /sys/class/net/${DNS_INTERFACE_NAME}/operstate)" = "down" ]; then
	ip link set ${DNS_INTERFACE_NAME} up
fi
if [ "$(ip addr show ${DNS_INTERFACE_NAME} | grep -o "inet [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | grep -o "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*")" != "${DNS_INTERFACE_IP}" ]; then
	ip address add ${DNS_INTERFACE_IP}/24 dev ${DNS_INTERFACE_NAME}
fi

# Redsocks needs a redsocks user to work properly with our setup
id -u redsocks > /dev/null 2>&1 || (echo "ERROR: redsocks user doesn't exist" && exit 1)

# Set up iptables chain for redsocks
$IPTABLES -t nat -N REDSOCKS

# Use every line in the no_proxy file as an IP/subnet to not redirect through redsocks
if [ -f "$NOPROXYFILE" ]; then
	info "Noproxy configuration found in $NOPROXYFILE ..."
	while IFS= read -r line || [ -n "${line}" ]; do
		echo "Setting no proxy for $line ..."
		$IPTABLES -t nat -A REDSOCKS -d "$line" -j RETURN
	done < "$NOPROXYFILE"
fi

# Setup a new user chain for redsocks
$IPTABLES -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
$IPTABLES -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
$IPTABLES -t nat -A REDSOCKS -d 100.64.0.0/10 -j RETURN
$IPTABLES -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
$IPTABLES -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
$IPTABLES -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
$IPTABLES -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
$IPTABLES -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
$IPTABLES -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN
$IPTABLES -t nat -A REDSOCKS -p tcp -j DNAT --to 10.114.103.1:12345

if grep ^dnsu2t /mnt/boot/system-proxy/redsocks.conf > /dev/null 2>&1; then
	# If dnsu2t module is enabled in redsocks, redirect any DNS UDP packets to
	# REDSOCKS to force DNS over TCP
	$IPTABLES -t nat -A OUTPUT -p udp -m owner ! --uid-owner redsocks -j DNAT --dport 53 --to-destination 10.114.103.1:5313
	$IPTABLES -t nat -A PREROUTING -p udp -j DNAT --dport 53 --to-destination 10.114.103.1:5313
fi

# Redirect TCP connections to redsocks
$IPTABLES -t nat -A OUTPUT -m owner --uid-owner redsocks -p tcp --dport 53 -j REDSOCKS
$IPTABLES -t nat -A OUTPUT -m owner ! --uid-owner redsocks -p tcp -j REDSOCKS
$IPTABLES -t nat -A PREROUTING -p tcp -j REDSOCKS
